<?php


namespace app\common\cachemodel;

use app\common\lib\PushQueue;
use app\common\lib\Util;
use app\common\model\BaseCache;
use Exception;
use think\Env;
use think\Log;
use XznsTools\cache\CacheManage;

/**
 * 定制报告问题记录模型
 * Class ZlcrCustomReportQuestion
 * @package app\common\cachemodel
 */
class ZlcrCustomReportQuestion extends BaseCache
{
    protected $table = 'wechat_backup_07_18_14_43_00.zlcr_custom_report_question';
    public $cacheModel = 'custom_report.question';

    protected $cacheIdKey = 'id';

    protected $pendingQuestionIdsCacheSelect = 9; // 定制报告待处理(待领取)问题 使用的redis库
    protected $pendingQuestionIdsListCacheKey = 'custom_report:pending_question_list:ids'; // 定制报告待处理(待领取)问题IDS List
    protected $pendingQuestionIdsCacheKey = 'custom_report:pending_question:ids'; // 定制报告待处理(待领取)问题IDS 有序集合
    public $completeAnswerTime;//接单后回答完成时长

    public function initialize(): void
    {
        parent::initialize();
        $this->completeAnswerTime = Env::get('queue.custom_report_answer6_delay');
    }

    /**
     * 获取档案已支付定制报告订单编号
     * @param $uid
     * @param $rid
     * @return array
     */
    public function getRecodeQuestionOrderIds($uid, $rid)
    {
        try
        {
            $where = "q.uid={$uid} AND q.status in (1,2,3,4,5,6,7,13) AND (qi.rid1=$rid OR qi.rid2=$rid)";
            return $this
                ->alias('q')
                ->join('wechat_backup_07_18_14_43_00.zlcr_custom_report_question_info qi', 'q.id=qi.qid')
                ->where($where)
                ->column('q.order_num', 'q.order_num');
        }
        catch (Exception $e)
        {
            Log::write('获取档案已支付定制报告订单编号失败：' . $e->getMessage() . '文件信息：' . $e->getFile() . ' : ' . $e->getLine() . PHP_EOL, 'error', true);
            return [];
        }
    }

    /**
     * 获取报告状态文案及跳转地址
     * @param $question
     * @return array
     */
    public function getReportStateDes($question): array
    {
        switch ($question['status'])
        {
            case 1://问题待审核
            case 2://问题待接单
                //获取当前报告的队列排名
                $num = $this->getCustomReportQueueRank($question['id']);
                //等待为0时，文案更改为  --- 您的报告进入占星师接单队列中，请稍等
                if ($num)
                {
                    $msg = '您的报告已进入占星师接单队列中，当前等待';
                    $msg_emphasis = $num;
                } else
                {
                    $msg = '您的报告进入占星师接单队列中，请稍等';
                    $msg_emphasis = '';
                }
                $report_status_list = [
                    'msg' => $msg,
                    'msg_emphasis' => $msg_emphasis,
                    'type' => 1,
                    'target' => 'local',
                    'link' => 'empty',
                    'order_des' => $msg . $msg_emphasis
                ];
                break;
            case 3://问题待解答
            case 4://解答待审核
            case 13://问题待解答（答案审核未通过)
                $msg = '您的报告已被占星师接单，预计完成时间';
                $payHour = date('G', $question['pay_time']);//获取当前支付的小时
                if ($payHour < 8 || $payHour >= 18)
                {
                    $toTime = strtotime(date('Y-m-d 08:00:00', strtotime('+1day', $question['pay_time'])));//获取第二天八点的时间戳
                    $msg_emphasis = date('m.d H:i', ($toTime + $this->completeAnswerTime));
                } else
                {
                    $msg_emphasis = date('m.d H:i', $question['astr_receiving_time'] + $this->completeAnswerTime);
                }
                $report_status_list = [
                    'msg' => $msg,
                    'msg_emphasis' => $msg_emphasis,
                    'type' => 2,
                    'target' => 'local',
                    'link' => 'empty',
                    'order_des' => $msg . $msg_emphasis
                ];
                $getWay = $question['get_way'] ?? 1;
                $time = time();
                if ($getWay === 2 && $time - $question['pay_time'] > 21600)
                {   // 指定咨询师
                    $toast = urlencode('是否取消订单？');
                    $report_status_list = [
                        'msg' => '咨询师还未回复，',
                        'msg_emphasis' => '取消订单',
                        'type' => 3,
                        'target' => 'local',
                        'link' => "custom_report_cancel?order_id={$question['order_num']}&status={$question['status']}&toast={$toast}&need_auth=2",
                        'order_des' => $msg . $msg_emphasis
                    ];
                }
                break;
            case 5://已完成待评价
            case 6://已评价待审核
            case 7://评价已审核完成
                $msg = '您的报告已被占星师火速完成';
                $msg_emphasis = '点击查看';
                $report_status_list = [
                    'msg' => $msg,
                    'msg_emphasis' => $msg_emphasis,
                    'type' => 3,
                    'target' => 'local',
                    'link' => "custom_report_result_info?id={$question['id']}&type=3&need_auth=1",
                    'order_des' => $msg
                ];
                break;
            case 10://问题审核未通过失效
            case 11://订单派发超时失效
            case 12://占星师超时未完成失效
            case 14://占星师拒答两次失效
            case 15://退款百分之九十
            case 16://百分百退款
                $msg = '您的报告已失效';
                $msg_emphasis = '点击查看';
                $report_status_list = [
                    'msg' => $msg,
                    'msg_emphasis' => $msg_emphasis,
                    'type' => 4,
                    'target' => 'local',
                    'link' => "custom_report_result_info?id={$question['id']}&type=4&need_auth=1",
                    'order_des' => $msg
                ];
                break;
            default :
                $msg = '您的报告进入占星师接单队列中，请稍等';
                $msg_emphasis = '';
                $report_status_list = [
                    'msg' => $msg,
                    'msg_emphasis' => $msg_emphasis,
                    'type' => 1,
                    'target' => 'local',
                    'link' => 'empty',
                    'order_des' => $msg . $msg_emphasis
                ];
                break;
        }
        return $report_status_list;
    }


    /**
     *添加定制报告
     * @param $orders
     * @param $param
     * @return false|int|string
     * @throws Exception
     */
    public function addCustomReport($orders, $param)
    {
        $questionGoods = (new ZlcrCustomReportGoods())->getInfoById($orders['gid']);
        $questionName = $questionGoods['qtype'] == 1 ? $questionGoods['question_name'] : $param['problem'];
        $nowTime = time();
        //todo 固定问题无需审核直接等待接单
//        if ($questionGoods['qtype'] == 1)
//        {
//            $status = 2;
//        } else
//        {
//            $status = 1;
//        }


        $is_merge = $questionGoods['is_merge'];
        if ($questionGoods['qtype'] == 2 && $param['rid'] && $param['rid2'])
        {
            $is_merge = 1;
        }
        $astrId = $param['astr_id'] ?? 0;
        if ($astrId)
        {
            $getWay = 2;
        }
        $questionData = [
            'id' => Util::createCustomReportId(),
            'uid' => $orders['uid'],
            'order_num' => $orders['order_id'],
            'gid' => $questionGoods['id'],
            'question_name' => $questionName,
            'qtype' => $questionGoods['qtype'],
            'is_merge' => $is_merge,
            'tid' => $questionGoods['tid'],
            'status' => 0,
            'get_way' => $getWay ?? 1, // 接单方式 1=>抢单  2=>派单
            'create_time' => $nowTime,
            'pay_time' => 0,
            'astr_receiving_time' => 0,
            'astr_id' => $astrId,
            'check_time1' => 0,
            'check_time2' => 0,
            'answer_time' => 0,
            'is_back' => 0,
            'aid' => 0
        ];
        $qid = $this->saveData($questionData);
        $recodeModel = new Recode();
        $recodeData = [];
        $recodeData['recode1'] = $recodeModel->getInfoById($param['rid']);
        $recodeData['recode2'] = $recodeModel->getInfoById($param['rid2']);
        //添加问题详情数据
        $questionResult = [
            'qid' => $qid,
            'rid1' => $param['rid'],
            'rid2' => $param['rid2'],
            'answer_content' => '',
            'recode_info' => json_encode($recodeData, true),
        ];
        $questionResult['supplement_info'] = !empty($param['supplement_info']) ? json_encode($param['supplement_info'], true) : '';
        $questionResult['abnormal_supplement_info'] = !empty($param['abnormal_supplement_info']) ? json_encode($param['abnormal_supplement_info'], true) : '';
        (new ZlcrCustomReportQuestionInfo())->saveData($questionResult);
        if (!empty($param['abnormal_supplement_info']))
        {
            //处理违规补充问题
            $customReportInfo = (new AppConfig())->configInfo('custom_report');
            if (isset($customReportInfo['supplement_question']) && $customReportInfo['supplement_question'] == 1)
            {
                $msg = '问题编号: ' . $qid . "\r\n";
                foreach ($param['supplement_info'] as $item)
                {
                    if ($item['type'] == 1)
                    {
                        $msg .= '标题: ' . $item['title'] . "\r\n";
                        $msg .= '内容: ' . $item['content'] . "\r\n";
                    }
                }
                Util::sendZlcrMsg(8, [$msg]);
            }
        }
        return $qid;
    }


    /**
     * 定制报告订单入队
     * @param $order_id
     * @throws Exception
     */
    public function orderReportQueue($order_id): void
    {
        $nowTime = time();
        //根据订单编号获取问题信息
        $question = $this->getOrderNumQuestionFromCache($order_id);
        //todo 固定问题直接入队
//        if ($question['qtype'] == 1)
//        {
//            $this->listDataAdd($question['uid'], [$question['id'] => $question['id']], 1);
//            $this->CustomReportQueueAdd($question['id'], 1);        //接单list和排行榜list
//        } else
//        {
//            // 添加待审核数据信息
//            (new ZlcrContentCheck())->saveData([
//                'type' => 1, // 问题审核
//                'status' => 1,
//                'qid' => $question['id'],
//                'create_time' => $nowTime
//            ]);
//        }
        $question['pay_time'] = $nowTime;
        //首页报告列表添加数据
        $this->listDataAdd($question['uid'], [$question['id'] => $question['id']], 1);
        //接单list和排行榜list
        $this->CustomReportQueueAdd($question['id'], 1);

        //我的报告列表添加数据
        $this->listDataAdd($question['uid'], [$question['id'] => $question['id']], 2);
        $customReportQuestionModel = new ZlcrCustomReportQuestion();
        //问题指定占星师
        if ($question['astr_id'])
        {
            $astrModel = new ZlcrAstr();
            $updateData = [
                'status' => 3, // 问题待解答
                'pay_time' => $nowTime,
                'astr_receiving_time' => $nowTime, // 接单时间
            ];
            $customReportQuestionModel->updateData($question['uid'], $question['id'], $updateData); // 更新问题信息
            $astrModel->underwayTaskAdd($question['astr_id'], $question['id']); // 添加进行中的任务
            $astrInfo = (new ZlcrAstr())->getInfoById($question['astr_id'], ['tel']);
            Util::sendHySms([$astrInfo['tel']], '', 119292, []);
            //发送短信和消息
            (new ZlcrAstrMessage())->add($question['astr_id'], [
                'status' => 0,
                'is_read' => 0,
                'astr_id' => $question['astr_id'],
                'type' => 0,
                'title' => '定制报告新任务提醒',
                'content' => "你收到新的定制报告任务，请在6小时内完成提交。",
                'target' => 'local',
                'link' => "/astrologer/answer?qid={$question['id']}",
                'create_time' => time()
            ]);
            // 超时处理队列
            (new PushQueue())->customReportInvalid($question, 4, ['id' => $question['id'], 'astr_id' => $question['astr_id'], 'push_switch' => 1]);
        } else
        {
            $updateData = [
                'status' => 2, // 问题待接单
                'pay_time' => $nowTime,
            ];
            $customReportQuestionModel->updateData($question['uid'], $question['id'], $updateData); // 更新问题信息
            //问题超时队列
            (new PushQueue())->customReportInvalid($question, 1, ['id' => $question['id'], 'push_switch' => 1]);
        }
    }

    /**
     * 添加用户提问记录
     * @param $insertData
     * @return false|int|string
     */
    public function saveData($insertData)
    {
        try
        {
            $this->save($insertData);
        }
        catch (Exception $e)
        {
            return false;
        }
        return $insertData['id'];
    }

    /**
     * 修改问题信息
     * @param $uid
     * @param $id
     * @param $data
     * @return bool
     * @throws Exception
     */
    public function updateData($uid, $id, $data): bool
    {
        try
        {
            $this->where(['id' => (string)$id])->update($data);
        }
        catch (Exception $e)
        {
            return false;
        }
        if (isset($data['status']) && in_array($data['status'], [3, 4, 13], false))
        {
            if (isset($data['astr_id']))
            {
                $astr_id = $data['astr_id'];
            } else
            {
                $question = $this->getInfoById($id, ['astr_id']);
                $astr_id = $question['astr_id'];
            }
            CacheManage::getInstance()->setCacheConfig((new ZlcrAstr())->cacheModel)->setCacheKeyDetail('astr_ids', 2)->listAdd([$astr_id => $astr_id], 0, 'astr_ids');
        }
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $id)->setCache($data);
        //更新首页报告跑马灯列表
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(1)->rmCache('list');
        //更新我的报告列表
        CacheManage::getInstance()->setCacheConfig($this->cacheModel, $uid)->setListKeyType(2)->rmCache('list');
        return true;
    }

    /**
     * 缓存获取当前用户已支付的报告信息
     * @param $uid
     * @param int $type 1=>首页报告列表，2=>我的报告列表
     * @param array $reportStatus 报告状态(为空时默认查询所有报告状态)  0=>待支付 1=>问题待审核 2=>问题待接单 3=>问题待解答 4=>解答待审核 5=>已完成待评价 6=>已评价待审核 7=>评价已审核完成 10=>问题审核未通过失效 11=>订单派发超时失效 12=>占星师超时未完成失效 13=>问题待解答（答案审核未通过）14=>占星师拒答三次或申诉通过失效 15=>用户取消订单，金额退回90% 16=>用户取消订单，金额全部退回 ,
     * @param array $readStatus 阅读状态(为空时默认查询所有阅读状态)  0=>未读 1=>已读
     * @param int $page
     * @return array
     * @throws Exception
     */
    public function getUserQuestionReportFromCache($uid, $type = 1, $reportStatus = [], $readStatus = [], $page = -1): array
    {
        $result = CacheManage::getInstance()
            ->setCacheConfig($this->cacheModel, $uid)
            ->setPage($page)
            ->setSort('desc')
            ->setListKeyType($type)// 类型 用于分页 例如 0全部 1待支付 已支付 //
            ->getListPageDataIds(function () use ($uid, $reportStatus, $readStatus)
            {
                return $this->getUserQuestionReportIdsFromDms($uid, $reportStatus, $readStatus);
            });
        $ids = array_keys($result['data']);
        $result['data'] = $this->batchGetInfoByIds($ids);
        return [
            'ids' => $ids,
            'data' => $result
        ];
    }

    /**
     * 数据库获取当前用户的报告id
     * @param $uid
     * @param array $reportStatus 报告状态(为空时默认查询所有报告状态)
     * @param array $readStatus 阅读状态(为空时默认查询所有阅读状态)
     * @return array
     */
    public function getUserQuestionReportIdsFromDms($uid, $reportStatus = [], $readStatus = []): array
    {
        $where = "uid = {$uid}";
        if ($reportStatus)
        {
            $reportStatus = implode(',', $reportStatus);
            $where .= " and status in ({$reportStatus})";
        }
        if ($readStatus)
        {
            $readStatus = implode(',', $readStatus);
            $where .= " and is_read in ({$readStatus})";
        }
        try
        {
            $ids = $this->where($where)->order('id desc')->column('id');
            $idData = [];

            foreach ($ids as $qid)
            {
                $idData[$qid] = ['id' => $qid];
            }
        }
        catch (Exception $e)
        {
            $idData = [];
        }
        return $idData;
    }

    /**
     * 根据订单编号获取问题信息
     * @param $orderId
     * @return array
     * @throws Exception
     */
    public function getOrderNumQuestionFromCache($orderId): array
    {
        $ids = CacheManage::getInstance()->setCacheConfig('custom_report.order_question', $orderId)->ZsGetIocData('list', function () use ($orderId)
        {
            return $this->getOrderNumQuestionIdFromDms($orderId);
        });

        $idsArr = [];
        foreach ($ids as $idItem)
        {
            $idsArr[] = (string)$idItem;
        }

        return current($this->batchGetInfoByIds($idsArr));
    }

    /**
     * 根据订单编号获取问题id
     * @param $orderId
     * @return array|null
     */
    public function getOrderNumQuestionIdFromDms($orderId): ?array
    {
        try
        {
            $data = $this->where(['order_num' => $orderId])->column('id', 'id');
            $data = array_flip_key_value($data);
        }
        catch (Exception $e)
        {
            $data = [];
        }
        return $data;
    }

    /**
     * 重写数据时获取数据
     * @param $ids
     * @param $type
     * @param $sortType
     * @return array|false|string
     */
    public function getInfoByIdsInData($ids, $type, $sortType)
    {
        try
        {
            $data = $this
                ->order('id', 'DESC')
                ->where('id', 'in', $ids)
                ->column('id,uid,order_num,gid,question_name,qtype,is_merge,tid,status,create_time,astr_receiving_time,astr_id,check_time1,check_time2,answer_time,is_back,is_read,pay_time,invalid_time,get_way', 'id');
        }
        catch (Exception $e)
        {
            $data = [];
        }

        return $data;
    }

    public function batchGetInfoByIds($cids, $field = [])
    {
        $resData = parent::batchGetInfoByIds($cids, $field);

        return $this->dataInit($resData);
    }

    /**
     * 数据初始化
     * @param array $data
     * @return array
     */
    public function dataInit(array $data)
    {
        foreach ($data as $index => $itemData)
        {
            $data[$index] = arrayKeyData2int($itemData, ['id', 'uid', 'is_read', 'astr_id', 'gid', 'qtype', 'is_merge', 'tid', 'status', 'create_time', 'astr_receiving_time', 'check_time1', 'check_time2', 'answer_time', 'is_back', 'pay_time', 'invalid_time', 'get_way']);
        }

        return $data;
    }
    // --------------------------------------------定制报告 问题缓存-----------------------------------------------

    /**
     * 获取报告数量
     * @param array $notAnswerQuestion 拒答的问题ID
     * @return bool|int
     */
    public function getCustomReportQueueNum(array $notAnswerQuestion)
    {
        $redis = CacheManage::getInstance()->redisHandler; // 获取redis 操作对象

        $redis->select($this->pendingQuestionIdsCacheSelect); // 设置redis 使用库

        $qids = $redis->lRange($this->pendingQuestionIdsListCacheKey, 0, -1);

        $num = count(array_diff($qids, $notAnswerQuestion));

        $redis->select(0); // 还原设置redis 使用库 为0库

        return $num;
    }

    /**
     * 向问题池中 添加问题ID
     * @param $qId
     * @param int $type 1=>正常下单添加问题 2=>占星师拒绝回答问题 问题抛回问题池
     * @return int 返回总问题数
     */
    public function CustomReportQueueAdd($qId, int $type = 1): int
    {
        $redis = CacheManage::getInstance()->redisHandler; // 获取redis 操作对象

        $redis->select($this->pendingQuestionIdsCacheSelect); // 设置redis 使用库

        if ($type === 1)
        {
            $num = $redis->rPush($this->pendingQuestionIdsListCacheKey, $qId); // 列表添加
        } else
        {
            $num = $redis->lPush($this->pendingQuestionIdsListCacheKey, $qId); // 列表添加
        }

        $redis->zAdd($this->pendingQuestionIdsCacheKey, [], $qId, $qId); // 有序列表添加
        $redis->select(0); // 还原设置redis 使用库 为0库

        return $num;
    }

    /**
     * 将问题池中删除指定问题ID
     * @param $qId
     * @return int 返回删除元素的数量
     */
    public function CustomReportQueueDel($qId): int
    {
        $redis = CacheManage::getInstance()->redisHandler; // 获取redis 操作对象

        $redis->select($this->pendingQuestionIdsCacheSelect); // 设置redis 使用库

        $data = $redis->lRem($this->pendingQuestionIdsListCacheKey, $qId, 0);

        $redis->zRem($this->pendingQuestionIdsCacheKey, $qId);
        $redis->select(0);// 还原设置redis 使用库 为0库

        return $data;
    }

    /**
     * 领取问题 将问题池中移除一个 问题ID     【另一种思路，先取差集 然后在pop】
     * @param array $notQid // 拒绝过的问题ID
     * @return string|bool 移除元素数量
     */
    public function CustomReportQueuePop(array $notQid)
    {
        $redis = CacheManage::getInstance()->redisHandler; // 获取redis 操作对象

        $redis->select($this->pendingQuestionIdsCacheSelect); // 设置redis 使用库

        $notNewQid = [];
        $newQid = $redis->lPop($this->pendingQuestionIdsListCacheKey);

        while ($newQid !== false && in_array($newQid, $notQid, false))
        {
            array_unshift($notNewQid, $newQid);
            $newQid = $redis->lPop($this->pendingQuestionIdsListCacheKey);
        }

        if ($notNewQid)
        {   // 获取完问题后将问题重新抛回问题池
            array_unshift($notNewQid, $this->pendingQuestionIdsListCacheKey);
            call_user_func_array([$redis, 'lPush'], $notNewQid);
        }

        if ($newQid)
        {
            $redis->zRem($this->pendingQuestionIdsCacheKey, $newQid);
        }
        $redis->select(0); // 还原设置redis 使用库 为0库

        return $newQid === false ? false : (string)$newQid;
    }

    /**
     * 获取当前问题的队列排名（从小到大）
     * @param $id
     * @return bool|int
     */
    public function getCustomReportQueueRank($id)
    {
        $redis = CacheManage::getInstance()->redisHandler;
        $redis->select($this->pendingQuestionIdsCacheSelect);
        $num = $redis->zRank($this->pendingQuestionIdsCacheKey, $id);
        $redis->select(0);// 还原设置redis 使用库 为0库
        return $num;
    }
    // --------------------------------------------------------------------------------------------------
}
